//    Copyright (C) Kherty.  All rights reserved.
using System;
using OpenLS.Core.Serialization;

namespace OpenLS.Spreadsheet
{
    public class Top10Filter : Filter
    {
        internal override void ReadXmlCore(ReadContext context)
        {
            using (ReadContext c = context.Read(xmlName))
            {
                Top = c.GetOptionalBoolean("top", true);
                Percent = c.GetOptionalBoolean("percent", false);
                Value = c.GetDouble("val");
                FilterValue = c.GetOptionalDouble("filterVal");
            }
        }
        const string xmlName = "top10";

        internal override void WriteXmlCore(WriteContext context)
        {
            using (WriteContext c = context.Write(xmlName))
            {
                c.SetOptionalBoolean("top", Top, true);
                c.SetOptionalBoolean("percent", Percent, false);
                c.SetDouble("val", Value);
                c.SetOptionalDouble("filterVal", FilterValue);
            }
        }
        private bool _top = true;

        public bool Top
        {
            get { return _top; }
            set { _top = value; }
        }

        public bool Percent { get; set; }

        public double Value { get; set; }

        public double? FilterValue { get; set; }

        internal override bool GetValue(Cell cell, RangeAddress rangeAddress)
        {
            if (!(cell.Value is double))
                return false;
            if (lastRangeAddress == null || !lastRangeAddress.Value.Equals(rangeAddress))
                _distribution = new CellValueDistribution(new MultiCellsRange(cell.Worksheet, rangeAddress));
            var v = _distribution.GetTopValue((int) Value, !Top, Percent);
            double d = (double) cell.Value;
            return d >= v;
        }

        internal override Func<Cell, bool> GetCellEvaluator(Range range)
        {
            CellValueDistribution distribution = new CellValueDistribution(range);
            return c =>
                       {
                           if (!(c.Value is double))
                               return false;
                           var v = distribution.GetTopValue((int) Value, !Top, Percent);
                           double d = (double) c.Value;
                           return d >= v;
                       };
        }

        private CellValueDistribution _distribution;
        private RangeAddress? lastRangeAddress;
    }
}
